`timescale 1ns / 1ps

module vldrdy2apfifo
(
    input				in_empty_n,
    output				in_read,
    input				out_full_n,
    output				out_write,
    
    output              i_vld,
    input               i_rdy,

    input               o_vld,
    output              o_rdy
);
assign i_vld     = in_empty_n;
assign in_read   = in_empty_n & i_rdy;
assign o_rdy     = out_full_n;
assign out_write = out_full_n & o_vld;

endmodule


module aphs_interface #
(   
    parameter OUT_LEN = 1024
)
(
    input				ap_clk,
    input				ap_rst,
    input				ap_start,
    output reg			ap_done,
    input				ap_continue,
    output reg			ap_idle,
    output reg		 	ap_ready,
    input				ap_ce,
    
    input				out_succ
);

localparam	S0_IDLE	=	3'b001;
localparam	S1_RUN	=	3'b010;
localparam	S2_DONE	=	3'b100;
reg [2:0] cstate, nstate;

wire cnt_rst;
wire cnt_en;
wire cnt_last;

assign cnt_rst = ap_rst | cstate[0];
assign cnt_en  = cstate[1] & out_succ;

zq_counter #(
    .N  (OUT_LEN)
) inst_cnt
(
    .clk    (ap_clk),
    .rst    (cnt_rst),
    .clken  (cnt_en),
    .last   (cnt_last),
    .out    ()
);

always @ (posedge ap_clk) begin
	if (ap_rst) begin
		cstate <= S0_IDLE;
	end else begin
		cstate <= nstate;
	end
end

always @ (*) begin
	case(cstate)
		S0_IDLE: begin
            nstate = ap_start ? S1_RUN : S0_IDLE;
		end
		S1_RUN: begin
		    // nstate = cnt_last ? S2_DONE : S1_RUN;
		    nstate = (cnt_last & out_succ) ? S2_DONE : S1_RUN;
		end
		S2_DONE: begin
			nstate = S0_IDLE;
		end
		default: begin
			nstate = S0_IDLE;
		end
	endcase
end

reg	ap_done_reg;
always @ (posedge ap_clk) begin
	if (ap_rst) begin
		ap_done_reg <= 1'b0;
	end else begin
		if (ap_continue) begin
			ap_done_reg <= 1'b0;
		end else if (cstate[2]) begin
			ap_done_reg <= 1'b1;
		end
	end
end

always @ (*) begin
	if (cstate[2]) begin
		ap_done = 1'b1;
		ap_ready = 1'b1;
	end else begin
		ap_done = ap_done_reg;
		ap_ready = 1'b0;
	end
end

always @ (*) begin
	if ( ~ap_start & cstate[0] ) begin
		ap_idle = 1'b1;
	end else begin
		ap_idle = 1'b0;
	end
end

endmodule
